﻿using MultiLang;
namespace Rsdn.Janus
{
    using System;
    using System.Collections.Generic;
    using System.Data.Linq;
    using System.Linq;
    using System.Reactive.Subjects;
    using CoreServices.NavigationTree;
    using JetBrains.Annotations;
    using SmartApp;

    [Service(typeof(IVirtualForumTreeService))]
    public class VirtualForumTreeService : IVirtualForumTreeService, IDisposable
    {
        //private IFeature;
        private readonly IServiceProvider _serviceProvider;

        private readonly Dictionary<int, IVirtualForumProvider> _virtualForumNodes =
            new Dictionary<int, IVirtualForumProvider>();

        private readonly Subject<EventArgs> _treeChanged = new Subject<EventArgs>();

        public VirtualForumTreeService([NotNull] IServiceProvider serviceProvider)
        {
            if (serviceProvider == null)
                throw new ArgumentNullException("serviceProvider");               //MLHIDE

            _serviceProvider = serviceProvider;

            ExtensionsCache<VirtualForumProviderInfo, IVirtualForumProvider> extensionsCache =
                new ExtensionsCache<VirtualForumProviderInfo, IVirtualForumProvider>(_serviceProvider);

            IVirtualForumProvider[] navigationTreeProviders = extensionsCache.GetAllExtensions();
            foreach (IVirtualForumProvider virtualForimProvider in navigationTreeProviders)
            {
                INavigationTreeItemInfo itemInfo = virtualForimProvider.GetItemInfo("");
                if (itemInfo != null)
                {
                    if (!_virtualForumNodes.ContainsKey(itemInfo.Id))
                    {
                        _virtualForumNodes.Add(itemInfo.Id, virtualForimProvider);
                    }
                    else
                    {
                        throw new DuplicateKeyException(
                            string.Format(ml.ml_string(166, "Плагин с идентификатором {0} уже зарегистрирован"), itemInfo.Id));
                    }
                }
            }
        }

        #region Implementation of INavigationTreeService
        //public IEnumerable<Rsdn.Janus.ObjectModel.IFeature> GetRootNodes
        //{
        //    get { return null; }
        //}

        //public IObservable<EventArgs> TreeChanged
        //{
        //    get { return _treeChanged; }
        //}


        public IEnumerable<IVirtualForumProvider> GetVirtualForums()
        {
            return _virtualForumNodes
                .Select(pair => pair.Value)
                .Sort(vf => vf.GetItemInfo(string.Empty).PositionOrder);
        }

        #endregion

        #region Implementation of IDisposable

        public void Dispose()
        {
            _treeChanged.OnCompleted();
        }

        #endregion

        #region Private Members

        //private static IEnumerable<INavigationTreeNode> MergeNodes(
        //    IEnumerable<INavigationTreeNodeSource> nodeSources)
        //{
        //    return
        //        nodeSources
        //            .GroupBy(node => node.Name)
        //            .Select(grp => MergeNode(grp))
        //            .Sort(node => node.OrderIndex);
        //}

        //private static INavigationTreeNode MergeNode(
        //    IEnumerable<INavigationTreeNodeSource> nodeSources)
        //{
        //    var first = nodeSources.OfType<INavigationTreeNode>().FirstOrDefault();
        //    if (first == null)
        //        throw new ApplicationException();
        //    return nodeSources.IsSingle()
        //        ? first
        //        : new NavigationTreeNode(
        //            first.Name,
        //            first.Header,
        //            first.NavigationPageName,
        //            MergeNodes(
        //                nodeSources.SelectMany(
        //                    source =>
        //                    {
        //                        var defintionNode = source as INavigationTreeNode;
        //                        if (defintionNode != null)
        //                            return defintionNode.Childrens.Cast<INavigationTreeNodeSource>();
        //                        var extensionNode = source as INavigationTreeNodeExtension;
        //                        if (extensionNode != null)
        //                            return extensionNode.Childrens;
        //                        return Enumerable.Empty<INavigationTreeNodeSource>();
        //                    })),
        //                first.OrderIndex);
        //}

        #endregion
    }
}